﻿#include "FITKAbaqusAdaptorBoundary.h"
#include "InpKeyLineSpliter.h"
#include "FITKAbaqusINPReader.h"
#include "FITKAbaqusINPWriter.h"
#include "FITK_Kernel/FITKCore/FITKEnumTransformer.hpp"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAbstractBoundaryCondition.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaBoundaryConditionDisplacement.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaBoundaryConditionSymmetry.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaBoundaryConditionVelocity.h"
#include "FITK_Kernel/FITKAppFramework/FITKMessage.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAssembly.h"
#include "FITK_Component/FITKAbaqusData/FITKAbaqusPart.h"
#include "FITK_Component/FITKAbaqusData/FITKDataCase.h"
#include "FITK_Interface/FITKInterfaceModel/FITKComponentManager.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAmplitudeManager.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaLoadManager.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaBoundaryConditionManager.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaStepManager.h"
//#include <QtCore/qmath.h>
#include <QTextStream>
#include <QList>
#include <QDebug>
//命名空间
namespace IO
{
    QString FITKAbaqusAdaptorBoundary::getAdaptorClass()
    {
        return "IO::FITKAbaqusAdaptorBoundary";
    }

    bool FITKAbaqusAdaptorBoundary::adaptR()
    {
        //读取
        Interface::FITKAbaAbstractBoundaryCondition* boundary = dynamic_cast<Interface::FITKAbaAbstractBoundaryCondition*>(_dataObj);
        if (!boundary || !_reader || !_caseData || _keywordsLine.isEmpty())return false;
        bool readOK = false;
        //获取类型
        Interface::FITKAbaAbstractBoundaryCondition::FITKAbaBoundaryConditionType type = boundary->getBoundaryConditionType();
        if (type == Interface::FITKAbaAbstractBoundaryCondition::FITKAbaBoundaryConditionType::SymmetryAntisymmetryEncastre)
            readOK = this->boundaryConditionSymmetryR();
        else if (type == Interface::FITKAbaAbstractBoundaryCondition::FITKAbaBoundaryConditionType::DisplacementRotation)
            readOK = this->boundaryConditionDisplacementR();
        else if (type == Interface::FITKAbaAbstractBoundaryCondition::FITKAbaBoundaryConditionType::VelocityAngularVelocity)
            readOK = this->boundaryConditionVelocityR();
        if (readOK)
            this->setStepDeactiveR();
        return readOK;
    }
    bool FITKAbaqusAdaptorBoundary::adaptW()
    {
        //写出
        Interface::FITKAbaAbstractBoundaryCondition* boundary = dynamic_cast<Interface::FITKAbaAbstractBoundaryCondition*>(_dataObj);
        if (!boundary || !_writer || !_caseData)return false;
        bool writerOK = false;
        Interface::FITKAbaAbstractBoundaryCondition::FITKAbaBoundaryConditionType type = boundary->getBoundaryConditionType();
        if (type == Interface::FITKAbaAbstractBoundaryCondition::FITKAbaBoundaryConditionType::SymmetryAntisymmetryEncastre)
            writerOK = this->boundaryConditionSymmetryW();
        else if (type == Interface::FITKAbaAbstractBoundaryCondition::FITKAbaBoundaryConditionType::DisplacementRotation)
            writerOK = this->boundaryConditionDisplacementW();
        else if (type == Interface::FITKAbaAbstractBoundaryCondition::FITKAbaBoundaryConditionType::VelocityAngularVelocity)
            writerOK = this->boundaryConditionVelocityW();
        return writerOK;
    }

    void FITKAbaqusAdaptorBoundary::setCaseData(AbaqusData::FITKDataCase* caseData)
    {
        //设置算例数据
        _caseData = caseData;
        _tool.setCaseData(_caseData);
    }

    void FITKAbaqusAdaptorBoundary::setLineKeywords(QString line)
    {
        //设置行数据
        _keywordsLine = line;
    }

    void FITKAbaqusAdaptorBoundary::setWriterData(QString op, int stepId)
    {
        //设置要写出的op和对应的stepid
        _op = op;
        _stepId = stepId;
    }

    bool FITKAbaqusAdaptorBoundary::boundaryConditionSymmetryR()
    {
        //对称/反对称/固定边界条件数据存储
        Interface::FITKAbaBoundaryConditionSymmetry* boundary = dynamic_cast<Interface::FITKAbaBoundaryConditionSymmetry*>(_dataObj);
        if (!_reader || !_caseData || !boundary)return false;
        Core::FITKEnumTransfer<Interface::AbaSymmetryAntisymmetryEncastreType::SymmetryAntisymmetryEncastreType> boundaryLabel;
        // 回退一行, 处理数据
        _reader->backLine();
        QString line = _reader->readLine();
        QStringList str = line.split(',');
        if (str.size() < 2)return false;
        int instanceId = -1;
        //获取setid和约束类型
        int setID = _tool.getSetIDByName(str.at(0).trimmed(), -1, instanceId);
        bool isValid = false;
        auto elType = boundaryLabel.fromString(str.at(1).trimmed().toUpper(), isValid);
        if (!isValid || setID == -1)
            return false;
        boundary->setType(elType);
        boundary->setComponent(setID);
        boundary->setModel(instanceId);
        _typeU = 0;
        return true;
    }

    bool FITKAbaqusAdaptorBoundary::boundaryConditionDisplacementR()
    {
        //位移/旋转边界条件数据存储
        Interface::FITKAbaBoundaryConditionDisplacement* boundary = dynamic_cast<Interface::FITKAbaBoundaryConditionDisplacement*>(_dataObj);
        if (!_reader || !_caseData || !boundary)return false;
        //处理关键字
        InpKeyLineSpliter spl(_keywordsLine, _reader);
        //获取幅值曲线
        if (_caseData->getAmplitudeManager())
        {
            auto ampData = _caseData->getAmplitudeManager()->getDataByName(spl["amplitude"]);
            if (ampData)
                boundary->setAmplitudeId(ampData->getDataObjectID());
        }
        // 回退一行, 处理数据
        _reader->backLine();
        QString line = _reader->readLine();
        QStringList str = line.split(',');
        if (str.size() < 3)return false;
        bool ok = false;
        int instanceId = -1;
        //获取setid和自由度类型
        int setID = _tool.getSetIDByName(str.at(0).trimmed(), -1, instanceId);
        if (setID == -1) return false;
        boundary->setComponent(setID);
        boundary->setModel(instanceId);
        _typeU = str.at(1).trimmed().toInt(&ok);
        if (_typeU <= 0 || _typeU > 6 || _typeU != str.at(2).trimmed().toInt())return false;
        double value = 0.0;
        if (str.size() >= 4)
            value = str.at(3).trimmed().toDouble(&ok);
        if (!ok)return false;
        //插入数据
        if (_typeU == 1)
        {
            boundary->setU1State(true);
            boundary->setU1(value);
        }
        else if (_typeU == 2)
        {
            boundary->setU2State(true);
            boundary->setU2(value);
        }
        else if (_typeU == 3)
        {
            boundary->setU3State(true);
            boundary->setU3(value);
        }
        else if (_typeU == 4)
        {
            boundary->setUR1State(true);
            boundary->setUR1(value);
        }
        else if (_typeU == 5)
        {
            boundary->setUR2State(true);
            boundary->setUR2(value);
        }
        else if (_typeU == 6)
        {
            boundary->setUR3State(true);
            boundary->setUR3(value);
        }
        return true;
    }

    bool FITKAbaqusAdaptorBoundary::boundaryConditionVelocityR()
    {
        //速度/角速度边界条件数据存储
        Interface::FITKAbaBoundaryConditionVelocity* boundary = dynamic_cast<Interface::FITKAbaBoundaryConditionVelocity*>(_dataObj);
        if (!_reader || !_caseData || !boundary)return false;
        //处理关键字
        InpKeyLineSpliter spl(_keywordsLine, _reader);
        //获取幅值曲线
        if (_caseData->getAmplitudeManager())
        {
            auto ampData = _caseData->getAmplitudeManager()->getDataByName(spl["amplitude"]);
            if (ampData)
                boundary->setAmplitudeId(ampData->getDataObjectID());
        }
        // 回退一行, 处理数据
        _reader->backLine();
        QString line = _reader->readLine();
        QStringList str = line.split(',');
        if (str.size() < 3)return false;
        bool ok = false;
        int instanceId = -1;
        //获取setid和自由度类型
        int setID = _tool.getSetIDByName(str.at(0).trimmed(), -1, instanceId);
        if (setID == -1) return false;
        boundary->setComponent(setID);
        boundary->setModel(instanceId);
        _typeU = str.at(1).trimmed().toInt(&ok);
        if (_typeU <= 0 || _typeU > 6 || _typeU != str.at(2).trimmed().toInt())return false;
        double value = 0.0;
        if (str.size() >= 4)
            value = str.at(3).trimmed().toDouble(&ok);
        if (!ok)return false;
        //插入数据
        if (_typeU == 1)
        {
            boundary->setU1State(true);
            boundary->setU1(value);
        }
        else if (_typeU == 2)
        {
            boundary->setU2State(true);
            boundary->setU2(value);
        }
        else if (_typeU == 3)
        {
            boundary->setU3State(true);
            boundary->setU3(value);
        }
        else if (_typeU == 4)
        {
            boundary->setUR1State(true);
            boundary->setUR1(value);
        }
        else if (_typeU == 5)
        {
            boundary->setUR2State(true);
            boundary->setUR2(value);
        }
        else if (_typeU == 6)
        {
            boundary->setUR3State(true);
            boundary->setUR3(value);
        }
        return true;
    }

    bool FITKAbaqusAdaptorBoundary::boundaryConditionSymmetryW()
    {
        //对称/反对称/固定边界条件数据存储
        Interface::FITKAbaBoundaryConditionSymmetry* boundary = dynamic_cast<Interface::FITKAbaBoundaryConditionSymmetry*>(_dataObj);
        if (!_writer || !_caseData || !boundary)return false;
        QTextStream* stream = _writer->getStream();
        *stream << QString("** Name: %1  Type: %2").arg(boundary->getDataObjectName()).arg("Symmetry/Antisymmetry/Encastre") << endl;
        //写出Boundary
        QString lineOne = "*Boundary";
        if (!_op.isEmpty())
            lineOne += _op;
        if (_stepId == -1)
        {
            *stream << lineOne << endl;
            return true;
        }
        *stream << lineOne << endl;
        //获取set
        auto set = boundary->getComponentObj();
        if (!set)return false;
        QString setName = set->getDataObjectName();
        setName = setName.contains(' ') ? QString("\"%1\"").arg(setName) : setName;
        //用于判断set是否在part下
        if (boundary->getModelObj() && boundary->getModelID() != set->getAbsModelID() && boundary->getModelObj()->getAbsModelType() == Interface::FITKModelEnum::AbsModelType::AssInstance)
        {
            QString name = boundary->getModelObj()->getDataObjectName();
            name = name.contains(' ') ? QString("\"%1\"").arg(name) : name;
            setName = name + "." + setName;
        }
        //写出数据
        bool ok = false;
        Core::FITKEnumTransfer<Interface::AbaSymmetryAntisymmetryEncastreType::SymmetryAntisymmetryEncastreType> boundaryLabel;
        QString boundaryFlag = boundaryLabel.toStrting((Interface::AbaSymmetryAntisymmetryEncastreType::SymmetryAntisymmetryEncastreType)boundary->getType(), ok);
        if (!ok)return false;
        *stream << QString("%1, %2").arg(setName).arg(boundaryFlag) << endl;
        return true;
    }

    bool FITKAbaqusAdaptorBoundary::boundaryConditionDisplacementW()
    {
        //位移/旋转边界条件数据存储
        Interface::FITKAbaBoundaryConditionDisplacement* boundary = dynamic_cast<Interface::FITKAbaBoundaryConditionDisplacement*>(_dataObj);
        if (!_writer || !_caseData || !boundary)return false;
        QTextStream* stream = _writer->getStream();
        *stream << QString("** Name: %1  Type: %2").arg(boundary->getDataObjectName()).arg("Displacement/Rotation") << endl;
        //写出Boundary
        QString lineOne = "*Boundary";
        if (!_op.isEmpty())
            lineOne += _op;
        if (_stepId == -1)
        {
            *stream << lineOne << endl;
            return true;
        }
        auto ampData = _caseData->getAmplitudeManager()->getDataByID(boundary->getAmplitudeId(_stepId));
        if (ampData)
        {
            QString ampName = ampData->getDataObjectName();
            ampName = ampName.contains(' ') ? QString("\"%1\"").arg(ampName) : ampName;
            lineOne += QString(", amplitude=%1").arg(ampName);
        }
            
        *stream << lineOne << endl;
        //获取set
        auto set = boundary->getComponentObj();
        if (!set)return false;
        QString setName = set->getDataObjectName();
        setName = setName.contains(' ') ? QString("\"%1\"").arg(setName) : setName;
        //用于判断set是否在part下
        if (boundary->getModelObj() && boundary->getModelID() != set->getAbsModelID() && boundary->getModelObj()->getAbsModelType() == Interface::FITKModelEnum::AbsModelType::AssInstance)
        {
            QString name = boundary->getModelObj()->getDataObjectName();
            name = name.contains(' ') ? QString("\"%1\"").arg(name) : name;
            setName = name + "." + setName;
        }
        if (boundary->getU1State(_stepId))
        {
            if(fabsl(boundary->getU1(_stepId)) < 1e-15)
                *stream << setName << ", 1, 1" << endl;
            else
                *stream << setName << ", 1, 1" << ", " << _writer->double2String(boundary->getU1(_stepId), 9, 0) << endl;
        }
        if (boundary->getU2State(_stepId))
        {
            if (fabsl(boundary->getU2(_stepId)) < 1e-15)
                *stream << setName << ", 2, 2" << endl;
            else
                *stream << setName << ", 2, 2" << ", " << _writer->double2String(boundary->getU2(_stepId), 9, 0) << endl;
        }
        if (boundary->getU3State(_stepId))
        {
            if (fabsl(boundary->getU3(_stepId)) < 1e-15)
                *stream << setName << ", 3, 3" << endl;
            else
                *stream << setName << ", 3, 3" << ", " << _writer->double2String(boundary->getU3(_stepId), 9, 0) << endl;
        }
        if (boundary->getUR1State(_stepId))
        {
            if (fabsl(boundary->getUR1(_stepId)) < 1e-15)
                *stream << setName << ", 4, 4" << endl;
            else
                *stream << setName << ", 4, 4" << ", " << _writer->double2String(boundary->getUR1(_stepId), 9, 0) << endl;
        }
        if (boundary->getUR2State(_stepId))
        {
            if (fabsl(boundary->getUR2(_stepId)) < 1e-15)
                *stream << setName << ", 5, 5" << endl;
            else
                *stream << setName << ", 5, 5" << ", " << _writer->double2String(boundary->getUR2(_stepId), 9, 0) << endl;
        }
        if (boundary->getUR3State(_stepId))
        {
            if (fabsl(boundary->getUR3(_stepId)) < 1e-15)
                *stream << setName << ", 6, 6" << endl;
            else
                *stream << setName << ", 6, 6" << ", " << _writer->double2String(boundary->getUR3(_stepId), 9, 0) << endl;
        }
        return true;
    }

    bool FITKAbaqusAdaptorBoundary::boundaryConditionVelocityW()
    {
        //速度/角速度边界条件数据存储
        Interface::FITKAbaBoundaryConditionVelocity* boundary = dynamic_cast<Interface::FITKAbaBoundaryConditionVelocity*>(_dataObj);
        if (!_writer || !_caseData || !boundary)return false;
        QTextStream* stream = _writer->getStream();
        *stream << QString("** Name: %1  Type: %2").arg(boundary->getDataObjectName()).arg("Velocity/Angular velocity") << endl;
        //写出Boundary
        QString lineOne = "*Boundary";
        if (!_op.isEmpty())
            lineOne += _op;
        if (_stepId == -1)
        {
            *stream << lineOne << endl;
            return true;
        }
        auto ampData = _caseData->getAmplitudeManager()->getDataByID(boundary->getAmplitudeId(_stepId));
        if (ampData)
        {
            QString ampName = ampData->getDataObjectName();
            ampName = ampName.contains(' ') ? QString("\"%1\"").arg(ampName) : ampName;
            lineOne += QString(", amplitude=%1").arg(ampName);
        }
        lineOne += ", type=VELOCITY";
        *stream << lineOne << endl;
        //获取set
        auto set = boundary->getComponentObj();
        if (!set)return false;
        QString setName = set->getDataObjectName();
        setName = setName.contains(' ') ? QString("\"%1\"").arg(setName) : setName;
        //用于判断set是否在part下
        if (boundary->getModelObj() && boundary->getModelID() != set->getAbsModelID() && boundary->getModelObj()->getAbsModelType() == Interface::FITKModelEnum::AbsModelType::AssInstance)
        {
            QString name = boundary->getModelObj()->getDataObjectName();
            name = name.contains(' ') ? QString("\"%1\"").arg(name) : name;
            setName = name + "." + setName;
        }
        if (boundary->getU1State(_stepId))
        {
            if (fabsl(boundary->getU1(_stepId)) < 1e-15)
                *stream << setName << ", 1, 1" << endl;
            else
                *stream << setName << ", 1, 1" << ", " << _writer->double2String(boundary->getU1(_stepId), 9, 0) << endl;
        }
        if (boundary->getU2State(_stepId))
        {
            if (fabsl(boundary->getU2(_stepId)) < 1e-15)
                *stream << setName << ", 2, 2" << endl;
            else
                *stream << setName << ", 2, 2" << ", " << _writer->double2String(boundary->getU2(_stepId), 9, 0) << endl;
        }
        if (boundary->getU3State(_stepId))
        {
            if (fabsl(boundary->getU3(_stepId)) < 1e-15)
                *stream << setName << ", 3, 3" << endl;
            else
                *stream << setName << ", 3, 3" << ", " << _writer->double2String(boundary->getU3(_stepId), 9, 0) << endl;
        }
        if (boundary->getUR1State(_stepId))
        {
            if (fabsl(boundary->getUR1(_stepId)) < 1e-15)
                *stream << setName << ", 4, 4" << endl;
            else
                *stream << setName << ", 4, 4" << ", " << _writer->double2String(boundary->getUR1(_stepId), 9, 0) << endl;
        }
        if (boundary->getUR2State(_stepId))
        {
            if (fabsl(boundary->getUR2(_stepId)) < 1e-15)
                *stream << setName << ", 5, 5" << endl;
            else
                *stream << setName << ", 5, 5" << ", " << _writer->double2String(boundary->getUR2(_stepId), 9, 0) << endl;
        }
        if (boundary->getUR3State(_stepId))
        {
            if (fabsl(boundary->getUR3(_stepId)) < 1e-15)
                *stream << setName << ", 6, 6" << endl;
            else
                *stream << setName << ", 6, 6" << ", " << _writer->double2String(boundary->getUR3(_stepId), 9, 0) << endl;
        }
        return true;
    }

    void FITKAbaqusAdaptorBoundary::setStepDeactiveR()
    {
        if (_typeU < 0)return;
        Interface::FITKAbaAbstractBoundaryCondition* boundary = dynamic_cast<Interface::FITKAbaAbstractBoundaryCondition*>(_dataObj);
        if (!_caseData || !boundary)return;
        //获取管理器
        auto bcManager = _caseData->getBCManager();
        if (!bcManager)return;
        int count = bcManager->getDataCount();
        //获取创建的stepid
        int stepId = boundary->getCreatedStep();
        //获取集合id
        int setId = boundary->getComponentID();
        //获取类型
        Interface::FITKAbaAbstractBoundaryCondition::FITKAbaBoundaryConditionType type = boundary->getBoundaryConditionType();
        //获取集合一致的边界在当前step中取消激活
        for (int i = 0; i < count; ++i)
        {
            Interface::FITKAbaAbstractBoundaryCondition* data = dynamic_cast<Interface::FITKAbaAbstractBoundaryCondition*>(bcManager->getDataByIndex(i));
            if (!data || data->getCreatedStep() == stepId || data->getDeactiveStep() != -1) continue;
            if (setId != data->getComponentID())continue;
            if (type == Interface::FITKAbaAbstractBoundaryCondition::FITKAbaBoundaryConditionType::SymmetryAntisymmetryEncastre)
            {
                Interface::FITKAbaBoundaryConditionSymmetry* dataValue = dynamic_cast<Interface::FITKAbaBoundaryConditionSymmetry*>(data);
                if(dataValue)
                    dataValue->setDeactiveStep(stepId);
            }
            else if (_typeU > 0 && _typeU <= 6)
            {
                Interface::FITKAbaBoundaryConditionDisplacement* dataValue = dynamic_cast<Interface::FITKAbaBoundaryConditionDisplacement*>(data);
                if (!dataValue)continue;
                if (_typeU == 1 && dataValue->getU1State())
                {
                    dataValue->setDeactiveStep(stepId);
                }
                else if (_typeU == 2 && dataValue->getU2State())
                {
                    dataValue->setDeactiveStep(stepId);
                }
                else if (_typeU == 3 && dataValue->getU3State())
                {
                    dataValue->setDeactiveStep(stepId);
                }
                else if (_typeU == 4 && dataValue->getUR1State())
                {
                    dataValue->setDeactiveStep(stepId);
                }
                else if (_typeU == 5 && dataValue->getUR2State())
                {
                    dataValue->setDeactiveStep(stepId);
                }
                else if (_typeU == 6 && dataValue->getUR3State())
                {
                    dataValue->setDeactiveStep(stepId);
                }
            }
        }
        
    }

}
